#include "ServiceManager.h"
#include <google/protobuf/descriptor.h>
#include "options.pb.h"
namespace emoney {
    ServiceManager::ServiceManager() {}

    ServiceManager::~ServiceManager() {

        for (size_t i = 0; i < m_sevices.size(); i++) {
            delete m_sevices[i];
        }

        m_sevices.clear();
    }

    ServiceManager& ServiceManager::instance() {
        static ServiceManager inst;
        return inst;
    }

    void ServiceManager::add_service(google::protobuf::Service* pService) {

        if (pService == nullptr) {
            return;
        }

        for (size_t i = 0; i < m_sevices.size(); i++) {
            if (m_sevices[i] == pService || m_sevices[i]->GetDescriptor()->name() == pService->GetDescriptor()->name()) {
                return ;
            }
        }

        m_sevices.push_back(pService);
    }

    const google::protobuf::MethodDescriptor* ServiceManager::getMethod(const std::string& methodName) {

        for (size_t i = 0; i < m_sevices.size(); i++) {
            const google::protobuf::ServiceDescriptor* sd = m_sevices[i]->GetDescriptor();
            const google::protobuf::MethodDescriptor* md = nullptr;
            for (int i = 0; i < sd->method_count(); i++) {
                md = sd->method(i);
                auto protoIdOrg = md->options().GetExtension(::emrpc::ProtoId);

                if (protoIdOrg == methodName) {
                    return md;
                }
            }
        }
        return nullptr;
    }

    bool ServiceManager::makeMessage(const std::string& methodName,
                                     google::protobuf::Message*& pbMsgReq,
                                     google::protobuf::Message*& pbMsgResp,
                                     google::protobuf::Service*& service,
                                     const google::protobuf::MethodDescriptor*& md) {

        const google::protobuf::ServiceDescriptor* sd = nullptr;

        for (size_t i = 0; i < m_sevices.size(); i++) {
            service = m_sevices[i];
            sd = service->GetDescriptor();
            for (int i = 0; i < sd->method_count(); i++) {
                md = sd->method(i);
                auto protoIdOrg = md->options().GetExtension(::emrpc::ProtoId);
                if (protoIdOrg == methodName) {
                    break;
                }
            }
        }

        if (sd != nullptr && md != nullptr && service != nullptr) {
            pbMsgReq = service->GetRequestPrototype(md).New();
            pbMsgResp = service->GetResponsePrototype(md).New();
            return true;
        }

        return false;
    }

}